CREATE OR REPLACE FUNCTION st_unitecascade_garray(geometry[], iter int, startcount int)
RETURNS geometry AS
$$
SELECT CASE
WHEN array_upper($1,1) < 5 OR  array_upper($1,1) BETWEEN 0 AND ln($3 + 1)/ln($2 + 1) THEN st_unite_garray($1)
ELSE st_unitecascade_garray(ARRAY(SELECT st_unite_garray($1[i:least(i + CAST(ln($3 + 1)/ln($2 + 1) As int) - 1,array_upper($1,1))]) As geom
FROM generate_series(1, array_upper($1,1), CAST(ln($3 + 1)/ln($2 + 1) As int)) As i), $2 + 1, $3)
END
$$
LANGUAGE 'sql' IMMUTABLE;

CREATE OR REPLACE FUNCTION st_unitecascade_garray_sort(geometry[])
RETURNS geometry AS
$$
SELECT CASE
WHEN array_upper($1,1) < 10  THEN st_unite_garray($1)
ELSE st_unitecascade_garray(ARRAY(SELECT ($1)[s] FROM
generate_series(1, array_upper($1, 1)) AS s
--ORDER BY ST_SnapToGrid(ST_Centroid(($1)[s]),0.1)
) , 2, array_upper($1,1))
END;
$$
LANGUAGE 'sql' IMMUTABLE;

--DROP AGGREGATE st_cascadeunion(geometry);

CREATE AGGREGATE st_cascadeunion(geometry) (
  SFUNC=st_geom_accum,
  STYPE=geometry[],
  FINALFUNC=st_unitecascade_garray_sort
);


-- usage:
--44,453 ms = 45 secs = wow! SELECT 44453/1000.00
/*
SELECT st_unitecascade_garray_sort(ARRAY(SELECT the_geom FROM sample_poly));

SELECT st_collect(geometry) from (select * from sshiap_splits limit 1000) a;

SELECT st_union(geometry) from (select * from sshiap_splits limit 1000) a;

SELECT st_cascadeunion(geometry) from (select * from sshiap_splits limit 1000) a;
*/